/*
Copyright (C) 2009-2010 Xanadu Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "../provider/DataProvider.h"
#include <Winsock2.h>
#include "MySQLM.h"

MySQL* MySQL::instance;
SimpleConnectionPool * MySQL::mypool = 0;

void MySQL::connectToMySQL() {
	mypool = new SimpleConnectionPool((char*)database.c_str(), (char*)host.c_str(), (char*)username.c_str(), (char*)password.c_str());
	try {
		mysqlpp::Connection *connection = mypool->grab();
		if(!connection->thread_aware()) {
			cout << "MySQL++ wasn't built with thread awareness!";
			cin.get();
			exit(1);
		}
		mypool->release(connection);
	}
	catch (mysqlpp::Exception& e) {
		cout << endl << e.what();
		cin.get();
		exit(1);
	}
}

int MySQL::getInt(char* table, int id, char* value) {
	stringstream query;
	query << "SELECT " << value << " FROM " << table << " WHERE ID=" << id;
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::StoreQueryResult res = maple_db->query(query.str()).store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if(!res.empty()) {
		return atoi(res[0][0]);
	}
	return 0;
}

int MySQL::getInt(char* table, char* whr, string wht, char* value) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT " << value << " FROM " << table << " WHERE " << whr << "=" << "'" << wht << "'";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if(!res.empty()) {
		return atoi(res[0][0]);
	}
	return 0;
}

vector<int> MySQL::getCharactersIds(int id, int maxchars) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	vector <int> ret;
	mysqlpp::Query query = maple_db->query();
	query << "SELECT ID FROM characters WHERE accountid=" << id;
	mysqlpp::StoreQueryResult res = query.store();
	for(char i=0; i<(char)res.num_rows() && i < maxchars; i++) {
		ret.push_back(atoi(res[i][0]));
	}
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	return ret;
}

bool MySQL::isString(char* table, char* whr, string wht) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT * FROM " << table << " WHERE " << whr << "=" << "'" << wht << "'";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if (!res.empty())
		return true;
	return false;
}

string MySQL::getString(char* table, char* whr, char* wht, char* value) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT " << value << " FROM " << table << " WHERE " << whr << "=" << "'" << wht << "'";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if(!res.empty())
		return string(res[0][0]);
	return string("");
}

string MySQL::getString(char* table, char* whr, int wht, char* value) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT " << value << " FROM " << table << " WHERE " << whr << "=" << "'" << wht << "'";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if(!res.empty())
		return string(res[0][0]);
	return string("");
}

void MySQL::setInt(char* table, char* wht, int id, int value) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "UPDATE " << table << " SET " << wht << "=" << "'" << value << "'" << " WHERE ID=" << "'" << id << "'";
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}

void MySQL::setString(char* table, char* wht, int id, char* value) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "UPDATE " << table << " SET " << wht << "=" << "'" << value << "'" << " WHERE ID=" << "'" << id << "'";
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}

void MySQL::createEquip(int equipid, int type, int charid) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "insert into equips(equipid, charid, iwatk, iwdef, slots, pos) values(" << equipid << "," << charid << ",";
	switch(type) {
		case 0x05: query << "0, 3, 7,"; break;
		case 0x06: query << "0, 2, 7,"; break;
		case 0x07: query << "0, 2, 5,"; break;
		case 0x0b: query << "17, 0, 7,"; break;
	}
	query << -type << ")";
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}

int MySQL::showEquips(int id, int equips[30][2]) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT equipid, pos FROM equips WHERE charid=" << id << " AND pos < 0";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	for(int i=0; i<(int)res.num_rows(); i++) {
		equips[i][0] = atoi(res[i][0]);
		equips[i][1] = atoi(res[i][1]);
	}
	return (int)res.num_rows();
}

void MySQL::getCharacter(int id, string info[32]) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT * FROM characters WHERE ID=" << id;
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if (res.empty()) {
		return;
	}
	for(int i = 0; i < 32; i++) {
		info[i] = string(res[0][i]);
	}
}

bool MySQL::checkIpBan(string ip) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "SELECT * FROM ipbans WHERE ip='" << ip << "'";
	mysqlpp::StoreQueryResult res = query.store();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
	if (!res.empty()) {
		return true;
	}
	return false;
}

void MySQL::addIpBan(string ip) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "INSERT INTO ipbans (ip) VALUES('"<< ip <<"')";
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}

void MySQL::unBan(string pname) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "UPDATE accounts SET banned=0, ban_reason=0 WHERE ID=" << getInt("characters", "name", pname, "userid");
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}

void MySQL::ban(string pname) {
	mysqlpp::Connection::thread_start();
	mysqlpp::Connection * maple_db = this->mypool->grab();
	mysqlpp::Query query = maple_db->query();
	query << "UPDATE accounts SET banned=1, ban_reason=1 WHERE ID=" << getInt("characters", "name", pname, "userid");
	query.execute();
	mypool->release(maple_db);
	mysqlpp::Connection::thread_end();
}